package com.sora.utils;

import javax.crypto.Cipher;
import javax.crypto.spec.SecretKeySpec;
import java.nio.charset.StandardCharsets;
import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;

/**
 * @Classname EncryptUtils
 * @Description 加密解密工具类
 * @Date 2023/06/24 14:51
 * @Author by Sora33
 */
public class EncryptUtils {

    /**
     * aes默认值 (16字节密钥，对应AES-128)
     */
    private static final String AES_VALUE = "NAYUTASORA331202";

    private static SecretKeySpec aesKey;
    private static Cipher aesCipherEncrypt;
    private static Cipher aesCipherDecrypt;

    static {
        try {
            // AES 密钥必须是 16、24 或 32 字节。这里使用 16 字节。
            aesKey = new SecretKeySpec(AES_VALUE.getBytes(StandardCharsets.UTF_8), "AES");

            // 初始化 AES 加密器
            aesCipherEncrypt = Cipher.getInstance("AES/ECB/PKCS5Padding");
            aesCipherEncrypt.init(Cipher.ENCRYPT_MODE, aesKey);

            // 初始化 AES 解密器
            aesCipherDecrypt = Cipher.getInstance("AES/ECB/PKCS5Padding");
            aesCipherDecrypt.init(Cipher.DECRYPT_MODE, aesKey);

        } catch (Exception e) {
            e.printStackTrace();
            throw new ExceptionInInitializerError("Failed to initialize AES ciphers: " + e.getMessage());
        }
    }

    /**
     * AES 加密
     *
     * @param var1 待加密字符串
     * @return 加密后的十六进制字符串
     */
    public static String encryAes(String var1) {
        try {
            byte[] encryptedBytes = aesCipherEncrypt.doFinal(var1.getBytes(StandardCharsets.UTF_8));
            return bytesToHex(encryptedBytes);
        } catch (Exception e) {
            e.printStackTrace();
            return null; // 或者抛出自定义异常
        }
    }

    /**
     * AES 解密
     *
     * @param var1 待解密十六进制字符串
     * @return 解密后的原始字符串
     */
    public static String unEncryAes(String var1) {
        try {
            byte[] decryptedBytes = aesCipherDecrypt.doFinal(hexToBytes(var1));
            return new String(decryptedBytes, StandardCharsets.UTF_8);
        } catch (Exception e) {
            e.printStackTrace();
            return null; // 或者抛出自定义异常
        }
    }

    /**
     * MD5 散列
     *
     * @param var1 待散列字符串
     * @return MD5 散列的十六进制字符串
     */
    public static String encryMD5(String var1) {
        return digestHex(var1, "MD5");
    }

    /**
     * SHA-1 散列
     *
     * @param var1 待散列字符串
     * @return SHA-1 散列的十六进制字符串
     */
    public static String encrySHA1(String var1) {
        return digestHex(var1, "SHA-1");
    }

    /**
     * SHA-256 散列
     *
     * @param var1 待散列字符串
     * @return SHA-256 散列的十六进制字符串
     */
    public static String encrySHA256(String var1) {
        return digestHex(var1, "SHA-256");
    }

    /**
     * SHA-512 散列
     *
     * @param var1 待散列字符串
     * @return SHA-512 散列的十六进制字符串
     */
    public static String encrySHA512(String var1) {
        return digestHex(var1, "SHA-512");
    }

    /**
     * 执行消息摘要并返回十六进制字符串
     */
    private static String digestHex(String input, String algorithm) {
        try {
            MessageDigest md = MessageDigest.getInstance(algorithm);
            byte[] hash = md.digest(input.getBytes(StandardCharsets.UTF_8));
            return bytesToHex(hash);
        } catch (NoSuchAlgorithmException e) {
            e.printStackTrace();
            return null;
        }
    }

    /**
     * 将字节数组转换为十六进制字符串
     */
    private static String bytesToHex(byte[] bytes) {
        StringBuilder hexString = new StringBuilder(2 * bytes.length);
        for (byte b : bytes) {
            String hex = Integer.toHexString(0xff & b);
            if (hex.length() == 1) {
                hexString.append('0');
            }
            hexString.append(hex);
        }
        return hexString.toString();
    }

    /**
     * 将十六进制字符串转换为字节数组
     */
    private static byte[] hexToBytes(String hexString) {
        int len = hexString.length();
        byte[] data = new byte[len / 2];
        for (int i = 0; i < len; i += 2) {
            data[i / 2] = (byte) ((Character.digit(hexString.charAt(i), 16) << 4)
                    + Character.digit(hexString.charAt(i + 1), 16));
        }
        return data;
    }
}